Universo Online
Web Sites Pessoais
Anterior Próximo Índice

Usando a Pilha para Passar Parâmetros

Linguagens de alto nível como Pascal ou C usam a pilha para passar parâmetros para rotinas. O endereço base da pilha está sempre no registrador SS (Stack Segment) e o deslocamento dentro da pilha está sempre no registror SP (Stack Pointer). O registrador SP é sempre inicializado com um valor mais alto do que o endereço base, e desse modo, cada vez que um valor de 2 bytes é colocado na pilha o ponteiro SP é diminuído de 2 bytes. Quando chamamos uma rotina com a instrução CALL o processador guarda o endereço seguinte à instrução na pilha. Ao término da rotina, uma instrução RET tira o endereço da pilha e coloca em IP, que é o ponteiro de instruções, para que ele volte a executar a partir desse endereço. Estamos, é claro, no mesmo segmento de código da rotina, então esta é uma chamada próxima. No caso de a rotina estar em outro segmento de código, a instrução CALL FAR coloca CS e IP na pilha, e recupera o endereço usando um RETF ao final do código da rotina. Por ora, ficamos apenas com a chamada próxima. Para colocar um dado na pilha usamos a instrução PUSH, e para limpar a pilha, usamos um RET seguido pelo número de bytes colocado como parâmetro:


segment CODIGO class=CODE
..start:
          mov ax, DADOS
          mov ds,ax
          ax, PILHA
          mov ss,ax
          mov sp,TOPO_PILHA
       
          push word MENSAGEM
          call PRINT_STRING
 
          mov ax,0x4c00
          int 0x21

PRINT_STRING:
          push bp
          mov bp,sp
          mov dx, [bp+4]
          mov ah,9
          int 0x21
          pop bp
          ret 2

segment DADOS class=DATA
       MENSAGEM db "Esta é uma mensagem imprimida por PRINT_STRING",'$'

segment PILHA STACK class=STACK align=16
       resb 0x100
      TOPO_PILHA:  

Em uma chamada próxima, como foi dito acima, o valor de IP (que sempre aponta para a próxima instrução) é colocado na pilha. Nesse passo, o ponteiro SP é decrementado de 2 bytes:

SP     = Valor incial de SP
SP - 2 = Valor de SP após colocar o parâmetro na pilha
SP - 4 = Valor de SP após a instrução call colocar IP na pilha
SP - 6 = Valor de SP após a rotina salvar BP na pilha
Nós copiamos, então, o último valor de SP em BP, porque BP é o ponteiro usado pelo 8086 para acessar um elemento na pilha. Somar 4 a BP significa fazer ele voltar 4 bytes na pilha, para acessar o parâmetro:

     BP + 4 = (SP - 6) + 4 = SP - 2

e como você pode ver acima, SP - 2 é exatamente o deslocamento do parâmetro na pilha.
Anterior Próximo Índice